package ui;

import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;

import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSpinner;
import javax.swing.JSplitPane;
import javax.swing.SpinnerNumberModel;

import ui.grafic.WizzardGrafic;
import databaseConnect.ScenarioWizzardRequests;
import datatypes.HostInformation;

public class ScenarioWizzard_TopologieGenerator extends ScenarioWizzard_Pane {

	private enum topology_types {
		      Line, Circle, Fortuity
		    };

	
	SpinnerNumberModel model = new SpinnerNumberModel( 1, 1, 1000, 1);
	JSpinner spin = new JSpinner( model );
	JCheckBox check1 = null;
	JCheckBox check2 = null;
	JRadioButton check3 = null;
	JRadioButton check4 = null;
	
	private JRadioButton x1 = null;
	private JRadioButton x2 = null;
	private JRadioButton x4 = null;
	private JRadioButton x8 = null;

	int selectOnlineState = 1;
	private JRadioButton selectAllOnline = null; //-->1
	private JRadioButton selectNoneOnline = null; //-->0
	private JRadioButton selectRandomOnline = null; //-->-1

	int selectHasServiceState = 1;
	private JRadioButton selectAllHasServices = null; //-->1
	private JRadioButton selectNoneHasServices = null; //-->0
	private JRadioButton selectRandomHasServices = null; //-->-1

	
	ButtonGroup bg = new ButtonGroup();
	private ButtonGroup bg2 = new ButtonGroup();
	private ButtonGroup bg3 = new ButtonGroup();

	JComboBox topo_type = new JComboBox(topology_types.values());
	JButton generieren = null;
    JButton update = null;
	
    JPanel backgroundPanel = new JPanel ();
	JPanel listPanel = new JPanel();
	JPanel graficPanel = new JPanel();
	CardLayout listPanelLayout = new CardLayout();
	CardLayout graficPanelLayout = new CardLayout();
		
	JSplitPane leftRight_split = new JSplitPane();
	JSplitPane topDown_split = new JSplitPane();
	
	
	//contains the HostIDs in right Order
	Vector<Integer> order = null;
	Vector<String> hostNames = null;
	Vector<Boolean> activeIndicator = null;
	Vector<Boolean> serviceIndicator = null;
	
	ScenarioWizzard_TopologieGenerator THIS = null;
	

	public ScenarioWizzard_TopologieGenerator (){
		super();
		THIS = this;
		bg.add(this.getServiceRadioButton());
		bg.add(this.getActiveRadioButton());
		bg2.add(this.getResolutionFactor1());
		bg2.add(this.getResolutionFactor2());
		bg2.add(this.getResolutionFactor4());
		bg2.add(this.getResolutionFactor8());
		bg3.add(this.getSelectAllOnlineButton());
		bg3.add(this.getSelectNoneOnlineButton());
		bg3.add(this.getSelectRandomOnlineButton());
		listPanel.setLayout(listPanelLayout);
		graficPanel.setLayout(graficPanelLayout);
		backgroundPanel.setLayout(new GridLayout(5,3));
		backgroundPanel.setMaximumSize(new Dimension(200, 200));
		backgroundPanel.add(new JLabel("Anzahl Hosts :"));
		backgroundPanel.add(spin);
		backgroundPanel.add(new JPanel());
		backgroundPanel.add(this.getPrintDistanceButton());
		backgroundPanel.add(new JPanel());
		this.topo_type.setSelectedIndex(topo_type.getItemCount()-1);
		backgroundPanel.add(this.topo_type);
		backgroundPanel.add(this.getPrintNamesButton());
		backgroundPanel.add(new JPanel());
		backgroundPanel.add(this.getGenerierenButton());
		backgroundPanel.add(check3);
		Box onlineBox = Box.createHorizontalBox();
		onlineBox.add(this.getSelectAllOnlineButton());
		onlineBox.add(this.getSelectNoneOnlineButton());
		onlineBox.add(this.getSelectRandomOnlineButton());
		backgroundPanel.add(onlineBox);
		backgroundPanel.add(this.getUpdateButton());
		backgroundPanel.add(check4);
		Box hasServicesBox = Box.createHorizontalBox();
		hasServicesBox.add(this.getSelectAllHasServicesButton());
		hasServicesBox.add(this.getSelectNoneHasServicesButton());
		hasServicesBox.add(this.getSelectRandomHasServicesButton());
		backgroundPanel.add(hasServicesBox);
		Box tmp = Box.createHorizontalBox();
		tmp.add(this.getResolutionFactor1());
		tmp.add(this.getResolutionFactor2());
		tmp.add(this.getResolutionFactor4());
		tmp.add(this.getResolutionFactor8());
		backgroundPanel.add(tmp);
				
		topDown_split.setOrientation(JSplitPane.VERTICAL_SPLIT);
		topDown_split.setTopComponent(backgroundPanel);
		topDown_split.setBottomComponent(graficPanel);
		leftRight_split.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
		leftRight_split.setLeftComponent(topDown_split);
		leftRight_split.setRightComponent(listPanel);
		//flow.add();
		this.setViewportView(leftRight_split);
	}

	private JButton getGenerierenButton(){
		if (generieren == null){
			generieren = new JButton("generieren");
			generieren.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent arg0) {
					int selectedNumberOfHosts = model.getNumber().intValue();
					int lastIDinDB = ScenarioWizzardRequests.getLastRowIDFromHostDescriptionTable();
					generatedContent = new HashMap<Integer, HostInformation>();
					order = null;
					activeIndicator = null;
					serviceIndicator = null;
					order = new Vector<Integer>();
					activeIndicator = new Vector<Boolean>();
					serviceIndicator = new Vector<Boolean>();
					hostNames = new Vector<String>();
					ActiveHostList = null;
					ServiceHostList = null;
					ActiveHostGrafic = null;
					ServiceHostGrafic = null;
					//this map contains every kombination xpos + | + ypos of generated Hosts in Simulation
					HashMap<String, Boolean> matchingSet = new HashMap<String, Boolean>();
					switch ((topology_types)topo_type.getSelectedItem()){
					case Fortuity:
						while (generatedContent.keySet().size() < selectedNumberOfHosts && generatedContent.keySet().size() < miniworld_height * miniworld_width){
							int xPos = (int) Math.round(Math.random() * ScenarioWizzard_Pane.miniworld_width);
							int yPos = (int) Math.round(Math.random() * ScenarioWizzard_Pane.miniworld_height);
							boolean active = getActiveState();
							boolean hasService = Math.round(Math.random()) == 1;
							if (matchingSet.get(xPos + "|" + yPos) == null){
								++lastIDinDB;
								Vector<String> services  = null;
								if (hasService){
									services = new Vector<String>();
									services.add("service" + lastIDinDB);
								}
								generatedContent.put(lastIDinDB, new HostInformation(lastIDinDB, xPos, yPos, active, services));
								activeIndicator.add(active);
								serviceIndicator.add(hasService);
								hostNames.add("Host " + lastIDinDB);
								matchingSet.put(xPos + "|" + yPos, true);
								order.add(lastIDinDB);
							}
						}
						break;
					case Line:
						int distanceBetweenTwoDevices  = ScenarioWizzard_Pane.miniworld_width / (selectedNumberOfHosts);
						int xPos_L = -1 * (distanceBetweenTwoDevices / 2);
						int yPos_L = ScenarioWizzard_Pane.miniworld_height / 2;
						while (generatedContent.keySet().size() < selectedNumberOfHosts && generatedContent.keySet().size() < miniworld_width){
							xPos_L = xPos_L + distanceBetweenTwoDevices;
							boolean active = getActiveState();
							boolean hasService = Math.round(Math.random()) == 1;
							if (matchingSet.get(xPos_L + "|" + yPos_L) == null){
								++lastIDinDB;
								Vector<String> services  = null;
								if (hasService){
									services = new Vector<String>();
									services.add("service" + lastIDinDB);
								}
								generatedContent.put(lastIDinDB, new HostInformation(lastIDinDB, xPos_L, yPos_L, active, services));
								activeIndicator.add(active);
								serviceIndicator.add(hasService);
								hostNames.add("Host " + lastIDinDB);
								matchingSet.put(xPos_L + "|" + yPos_L, true);
								order.add(lastIDinDB);
							}
						}
						break;
					case Circle:
						int x_m = ScenarioWizzard_Pane.miniworld_width / 2;
						int y_m = ScenarioWizzard_Pane.miniworld_height / 2;
						int r = 0;
						if (x_m < y_m){
							r = x_m - 5;
						} else {
							r = y_m - 5;
						}
						int angle_step = 360 / (selectedNumberOfHosts);
						int angle = 0;
						while (generatedContent.keySet().size() < selectedNumberOfHosts && generatedContent.keySet().size() < miniworld_height * miniworld_width){
							
							int xPos = (int) (x_m + (r * Math.cos((2 * Math.PI / 360) * angle)));
							int yPos = (int) (y_m + (r * Math.sin((2 * Math.PI / 360) * angle)));
							boolean active = getActiveState();
							boolean hasService = Math.round(Math.random()) == 1;
							if (matchingSet.get(xPos + "|" + yPos) == null){
								++lastIDinDB;
								Vector<String> services  = null;
								if (hasService){
									services = new Vector<String>();
									services.add("service" + lastIDinDB);
								}
								generatedContent.put(lastIDinDB, new HostInformation(lastIDinDB, xPos, yPos, active, services));
								activeIndicator.add(active);
								serviceIndicator.add(hasService);
								hostNames.add("Host " + lastIDinDB);
								matchingSet.put(xPos + "|" + yPos, true);
								order.add(lastIDinDB);
							}
							angle = angle + angle_step;
						}
						break;
					}
					listPanel.removeAll();
					listPanel.add(getActiveHostList(hostNames, activeIndicator), "active");
					listPanel.add(getServiceHostList(hostNames, serviceIndicator), "service");
					listPanel.updateUI();
					
					graficPanel.removeAll();
					graficPanel.add(getActiveHostGrafic(), "active");
					graficPanel.add(getServiceHostGrafic(), "service");
					graficPanel.updateUI();
				}			
			});
		}
		return generieren;
	}

	private JButton getUpdateButton(){
		if (update == null){
			update = new JButton("update");
			update.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent arg0) {
					if (getActiveRadioButton().isSelected()){
						Vector<Boolean> bool = getActiveHostList(null, null).get_Booleans();
						for (int i=0; i < bool.size(); i++){
							if (bool.get(i) != generatedContent.get(order.get(i)).isActive()){
								generatedContent.get(order.get(i)).setActive(bool.get(i));
							}
						}
						getActiveRadioButton().setSelected(true);
						ActiveHostGrafic = null;
						graficPanel.removeAll();
						graficPanel.add(getActiveHostGrafic(), "active");
						graficPanel.add(getServiceHostGrafic(), "service");
						graficPanelLayout.show(graficPanel, "active");
						graficPanel.updateUI();			
					} else {
						Vector<Boolean> bool = getServiceHostList(null, null).get_Booleans();
						for (int i=0; i < bool.size(); i++){
							if (bool.get(i) != generatedContent.get(order.get(i)).hasServices()){
								if (bool.get(i) == true){
									Vector<String> services = new Vector<String>();
									services.add("service" + order.get(i));
									generatedContent.get(order.get(i)).setServices(services);									
								} else {
									generatedContent.get(order.get(i)).setServices(null);																		
								}
							}
						}	
						ServiceHostGrafic = null;
						graficPanel.removeAll();
						graficPanel.add(getActiveHostGrafic(), "active");
						graficPanel.add(getServiceHostGrafic(), "service");
						graficPanelLayout.show(graficPanel, "service");
						graficPanel.updateUI();
					}
				}			
			});
		}
		return update;
	}

	private JRadioButton getResolutionFactor2(){
		if (x2 == null){
			x2 = new JRadioButton("2x");
			x2.setSelected(true);
			x2.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent arg0) {
						if (x2.isSelected()){
							getActiveHostGrafic().setResolution(2);
							getServiceHostGrafic().setResolution(2);
							getActiveHostGrafic().updateUI();
							getServiceHostGrafic().updateUI();
						} 
				}			
			});
		}
		return x2;
	}

	private JRadioButton getResolutionFactor4(){
		if (x4 == null){
			x4 = new JRadioButton("4x");
			x4.setSelected(true);
			x4.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent arg0) {
						if (x4.isSelected()){
							getActiveHostGrafic().setResolution(4);
							getServiceHostGrafic().setResolution(4);
							getActiveHostGrafic().updateUI();
							getServiceHostGrafic().updateUI();
						} 
				}			
			});
		}
		return x4;
	}
	private JRadioButton getResolutionFactor8(){
		if (x8 == null){
			x8 = new JRadioButton("8x");
			x8.setSelected(true);
			x8.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent arg0) {
						if (x8.isSelected()){
							getActiveHostGrafic().setResolution(8);
							getServiceHostGrafic().setResolution(8);
							getActiveHostGrafic().updateUI();
							getServiceHostGrafic().updateUI();
						} 
				}			
			});
		}
		return x8;
	}

	private JRadioButton getResolutionFactor1(){
		if (x1 == null){
			x1 = new JRadioButton("1x");
			x1.setSelected(true);
			x1.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent arg0) {
						if (x1.isSelected()){
							getActiveHostGrafic().setResolution(1);
							getServiceHostGrafic().setResolution(1);
							getActiveHostGrafic().updateUI();
							getServiceHostGrafic().updateUI();
						} 
				}			
			});
		}
		return x1;
	}

	private JCheckBox getPrintDistanceButton(){
		if (check1 == null){
			check1 = new JCheckBox("Distanz zeichnen");
			check1.setSelected(true);
			check1.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent arg0) {
					if (check1.isSelected()){
						getActiveHostGrafic().printRange(true);
						getServiceHostGrafic().printRange(true);
						getActiveHostGrafic().updateUI();
						getServiceHostGrafic().updateUI();
					} else {
						getActiveHostGrafic().printRange(false);
						getServiceHostGrafic().printRange(false);
						getActiveHostGrafic().updateUI();
						getServiceHostGrafic().updateUI();						
					}
				}			
			});
		}
		return check1;
	}

	private JCheckBox getPrintNamesButton(){
		if (check2 == null){
			check2 = new JCheckBox("Namen zeichnen");
			check2.setSelected(true);
			check2.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent arg0) {
					if (check2.isSelected()){
						getActiveHostGrafic().printNames(true);
						getServiceHostGrafic().printNames(true);
						getActiveHostGrafic().updateUI();
						getServiceHostGrafic().updateUI();
					} else {
						getActiveHostGrafic().printNames(false);
						getServiceHostGrafic().printNames(false);
						getActiveHostGrafic().updateUI();
						getServiceHostGrafic().updateUI();						
					}
				}			
			});
		}
		return check2;
	}

	
	private JRadioButton getActiveRadioButton(){
		if (check3 == null){
			check3 = new JRadioButton("aktiv/passiv hervorheben");
			check3.setSelected(true);
			check3.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent arg0) {
					if (check3.isSelected()){
						listPanelLayout.show(listPanel, "active");	
						graficPanelLayout.show(graficPanel, "active");
					}
				}			
			});
		}
		return check3;
	}

	private JRadioButton getServiceRadioButton(){
		if (check4 == null){
			check4 = new JRadioButton("mit/ohne Service hervorheben");
			check4.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent arg0) {
					if (check4.isSelected()){
						listPanelLayout.show(listPanel, "service");						
						graficPanelLayout.show(graficPanel, "service");
					}
				}			
			});
		}
		return check4;
	}
	
	private JRadioButton getSelectAllOnlineButton(){
		if (this.selectAllOnline == null){
			selectAllOnline = new JRadioButton("Alle");
			selectAllOnline.setSelected(true);
			selectAllOnline.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent arg0) {
					if (selectAllOnline.isSelected()){
						selectOnlineState = 1;
					}
				}			
			});
		}
		return selectAllOnline;
	}
	private JRadioButton getSelectRandomOnlineButton(){
		if (this.selectRandomOnline == null){
			selectRandomOnline = new JRadioButton("Zufall");
			selectRandomOnline.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent arg0) {
					if (selectRandomOnline.isSelected()){
						selectOnlineState = -1;
					}
				}			
			});
		}
		return selectRandomOnline;
	}
	
	private JRadioButton getSelectNoneOnlineButton(){
		if (this.selectNoneOnline == null){
			selectNoneOnline = new JRadioButton("Keinen");
			selectNoneOnline.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent arg0) {
					if (selectNoneOnline.isSelected()){
						selectOnlineState = 0;
					}
				}			
			});
		}
		return selectNoneOnline;
	}

	private JRadioButton getSelectAllHasServicesButton(){
		if (this.selectAllHasServices == null){
			selectAllHasServices = new JRadioButton("Alle");
			selectAllHasServices.setSelected(true);
			selectAllHasServices.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent arg0) {
					if (selectAllHasServices.isSelected()){
						selectHasServiceState = 1;
					}
				}			
			});
		}
		return selectAllHasServices;
	}
	private JRadioButton getSelectRandomHasServicesButton(){
		if (this.selectRandomHasServices == null){
			selectRandomHasServices = new JRadioButton("Zufall");
			selectRandomHasServices.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent arg0) {
					if (selectRandomHasServices.isSelected()){
						selectHasServiceState = -1;
					}
				}			
			});
		}
		return selectRandomHasServices;
	}
	
	private JRadioButton getSelectNoneHasServicesButton(){
		if (this.selectNoneHasServices == null){
			selectNoneHasServices = new JRadioButton("Keinen");
			selectNoneHasServices.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent arg0) {
					if (selectNoneHasServices.isSelected()){
						selectHasServiceState = 0;
					}
				}			
			});
		}
		return selectNoneHasServices;
	}

	
	private WizzardGrafic getActiveHostGrafic() {
		if (ActiveHostGrafic == null){	
			ActiveHostGrafic = new WizzardGrafic(miniworld_width, miniworld_height, range, new Vector<HostInformation> (generatedContent.values()), true);
    	}
    	return ActiveHostGrafic;
	}

	private WizzardGrafic getServiceHostGrafic() {
		if (ServiceHostGrafic == null){	
			ServiceHostGrafic = new WizzardGrafic(miniworld_width, miniworld_height, range, new Vector<HostInformation> (generatedContent.values()), false);
    	}
    	return ServiceHostGrafic;
	}

	public CheckList_Universal getActiveHostList (List<String> hostNames, Vector<Boolean> preselection){
    	if (ActiveHostList == null){	
    		ActiveHostList = new CheckList_Universal(hostNames, preselection);
    	}
    	return ActiveHostList;
    }
	
	public CheckList_Universal getServiceHostList (List<String> hostNames, Vector<Boolean> preselection){
    	if (ServiceHostList == null){	
    		ServiceHostList = new CheckList_Universal(hostNames, preselection);
    	}
    	return ServiceHostList;
    }
	
	public boolean getActiveState(){
		if (this.selectOnlineState == 1){
			return true;
		} else if (this.selectOnlineState == 0){
			return false;
		} else {
			return Math.round(Math.random()) == 1;
		}
	}
	
	public boolean getHasServiceState(){
		if (this.selectHasServiceState == 1){
			return true;
		} else if (this.selectHasServiceState == 0){
			return false;
		} else {
			return Math.round(Math.random()) == 1;
		}
	}
}